Servo
Animation for Total Annihilation
by Rhadamanthus (Rhad@flash.net)

Hello reader; thanks for trying out servo!
Servo is an animation program designed to bring more life, character, and complexity to the normally dull and formal BOS scripting language. Basically, Servo provides a graphical interface for animation, and then outputs the finished product as a BOS script.

Specifically, Servo outputs a BOS function; a coherent list of instructions which can be referenced in your unit's main script through the '#include' command. The unit's main script controls its logical behaviors - issues beyond the scope of Servo. Without the main script to govern it, the unit wouldn't know when to use its Servo-assisted animations; for this reason, you -will- need to know how to script in order to get your Servo-assisted animations into the game. You can find BOS scripting instructions at the major TA internet sites.

Before we look at Servo, let's consider the way TA units work. TA units are composed of geometric shapes arranged in heirarchies. Because of the heirarchical arrangement, it is possible to pose the model by reorienting its pieces. These reorientations can in turn be described through logical instructions to 'turn' or 'move' each piece around some or all of its axis. And by issuing a series of instructions over time, it is possible to give the model the illusion of fluid movement.

BOS script can also accomodate mathematically smooth motion, with instructions to 'spin' or turn a piece at a given speed, but such instructions are generally only useful for simple mechanical operations. On a larger scale, with many pieces rotating simultaneously (as in character animation, like a kbot walking or drawing a gun) it is much easier to describe the animation as a sequences of poses (sets of immediate instructions) separated by very short pauses (frames). This is how most character animation in TA works. So, Servo has two basic functions: 1) to create poses (groups of instructions) for the model, and 2) to arrange those instructions on a timeline.

1) The first task: create instructions.
Servo addresses this task in two simple ways. First, the model can be posed interactively in the 3d view. Second there is a panel called the instruction editor that displays all the instructions for a given piece at the current time. This allows for very specific editing; with the instruction editor you can tell a piece (for example) to rotate to exactly 30 degrees heading at the current time - or clear the pitch instruction for the current time.

The instruction editor only shows information for one piece at a time, so it becomes necessary to introduce a new concept: the active piece. The active piece is quite simply the piece whose present instructions are being manipulated. We will observe later how Servo keeps track of the active piece and identifies it in the views.

2) The second task: arrange and manipulate the instructions on a timeline.
From a design perspective, there are two obvious solutions to this problem. One could see the animation as TA sees it - as a single list of instructions where each instruction directs itself to a piece... Or one could look at the animation as a set of many lists - one for each piece in the model.
Servo takes the second approach, because it makes easier to make specific edits to each piece's animations. For example, you might realistically want to move all of the instructions for your unit's left arm to make part of its animation occur at a different time or rate. Such an operation would be difficult if instructions for the left arm were mixed in with instructions for the rest of the body.

So Servo has a separate instruction list for each piece in the model. In fact, Servo keeps a separate list for each channel(h/p/b/x/y/z) of each piece in the model - but editing is currently very limited at that level.

Conceptually, everything is working fine so far. There's just one question remaining: with a separate animation for each piece, how do you know which animations you are currently editing? This is where the concept of layers comes in. Servo has two layers: a foreground and a background. Pieces in the foreground are considered editable; pieces in the background are considered static. So, if you wanted to edit the animation for only the left arm, it becomes quite simple: bring the left arm to the foreground and put everything else in the background. Now you can rearrange the instructions for the left arm on the timeline, with the assurance that the animation for the rest of the model will remain unaffected.
Actually, the layers serve a dual purpose. Not only do they form the backbone of the animation editing system, but they also make it easier to pose the model; background pieces are made translucent and unselectable in the 3d view, making it easier to see and manipulate the foreground pieces which you intend to animate.

Now that we have an understanding of the concepts behind Servo, let's take a look at the actual program interface:

As you can see, the Servo GUI has six main sections: the menu, the tree/heirarchy view, the 3d view, the foreground deck, and the keyframe bay. What ever you intend to use Servo for, the menu is always the first element you have to interact with, so we'll address it first.

The Servo MENU:
Like most programs, Servo manages its base-level functions through a Windows menu. Servo's menu has three categories: object, bos, and view. The object and bos menus are more or less self-explanitory; servo can load objects, and load or save scripts. There is no need for a save object command, since servo doesn't edit the object itself; rather it just uses it to display the script.
The only interesting functions are in the view menu. This is where you can change certain aspects of how the 3d OpenGL view is rendered. The three branches of the view menu (active, foreground, background) correlate to Servo's interface. Each branch has options on how to render that layer on the current frame (shapes) and on frames prior to the current time.(trails)

The 3d View:
The 3d view is where you will spend the vast majority of your attention in the Servo interface. This one panel is where you will pose the model and view the animation.
As mentioned earlier, the Servo interface has a background, a foreground, and an active piece. When you load a model, all pieces are in the background by default. Each layer behaves differently in the view, and the view is color-coded to make them easily distinguishable. Background pieces show up in translucent blue, and are non-editable in the view. Foreground pieces show up red in the view, and are clickable. The Active piece will glow nuclear green/yellow to indicate its status.

The view is context-sensitive; it will react to the mouse differently depending on what you click on. If you click/drag and do not hit a foreground piece, you will be rotating the view. Left-drag to look around, and right-drag to pull the focus up or down vertically. Dragging both buttons will zoom in and out (regardless of whether there is a piece under the cursor), homeworld-style.
As soon as you click any foreground piece in the 3d view, it will become active; it will begin to glow, and current instructions will show up on the right. Furthermore, if you continue to drag the mouse on the piece it will rotate. Left-drag for heading/pitch; right-drag for bank.

The Instruction Editor:
This is your nuts-and-bolts control over the animation data. The information here represents the state of the Active Piece at the Current Time.

At the top, is a large button representing the hide/show command. Clicking it will cycle between three states: HIDE, SHOW, and no instruction. If there is no instruction on the current frame, the button will display "hidden" or "visible", depending on the state of the piece based on its most recent instruction.

Beneath the visibility button are a series of Numeric Entry Fields. Numeric Entry Fields (NEFs) are neato-keeno gadgets that are designed to let you enter numeric data in a way as painless as possible. Each NEF represents an instruction channel (h,p,b,x,y,z). If the piece has an instruction on the Current Time, the NEF for that channel will display the value in black. If there is no instruction, the NEF will display the current status of that channel based on the most recent instruction (if any) in milky-off-white.
The instruction a NEF represents can be edited in two ways: clicking on the NEF will allow you to type in a value directly (press ENTER when you're done), or, the NEF can be dragged left or right to change the value. The 3d view will update in real time as the value changes. Note, this is the easy way to rotate a piece around a single axis specifically.
To clear the instruction from a NEF, just right-click on it. The instruction will be removed from the animation, and the NEF will revert to off-white.

The Piece Heirarchy (tree) View:
The 3d view's capacity as a selection interface is very limited; it may be difficult to click on pieces if they become obscured, and it is completely impossible to click on pieces in the background or pieces that are hidden. This is where the tree view comes in; it allows you a hassle-free way to manage the background/foreground/active piece. Clicking on a piece in the tree will cycle from background to foreground to active and back to background again.

The Foreground Deck or Shelf:
As the name suggests, this area lists the foreground pieces. Each piece on the shelf has a blue grip area extending away from it into the timeline bay. Any instructions for the piece will show up on this grip at the appropriate time index. If you click on a piece's tag on the shelf, you will get an expanded view of the piece's Rotation, Translation, and visibility channels. Rotation and Translation can be further expanded to their per-axis components.
In the current version of Servo, this info is read-only; you can't make any changes directly (you must use the Instruction Editor) but in future versions the data will be more maleable.

The Timeline Bay:
This is where you take Servo's posing interface and harness it into usefull animation power. The top edge of the bay is an area called the main grip. It looks like a ruler. The marks on it represent game time; roughly 1000 ticks = 1 second of animation.

As stated before, Servo has animation channels for each piece. That animation data is displayed here in the bay. For every piece in the foreground, there is a grip extending across the bay. And on those grips, a yellow mark will appear wheneever the piece has an instruction.

Every time Servo encounters a foreground piece with an instruction, it draws a vertical orange index line on the display. The top of the line ends on the main grip, with a rectangular flag; this is the frame's handle. The mouse can drag it left or right across the timeline, moving all instructions on that frame. Like the view, the main grip is context sensitive. If you click and drag without hitting a flag, it will have the effect of shifting all of the indexes after the point you clicked.

Clicking anywhere in the bay (except the main grip) will create a new index. Indexes will automatically evaporate if they are empty when the foreground changes, or if all of the instructions they carry are deleted.

Finally, the main grip has an orange carat to indicate the Current Time. The Current Time is the frame being represented in the 3d view, and the frame being edited by the Instruction Editor. The Current Time is always on an index, and is defined as the most recent index to the left of the mouse. Thus, sweeping the mouse across the bay will have the effect of scrubbing the animation. When the mouse leaves the bay, the Current Time remains whereever it was when the mouse left.

Code Grip:
In case you want to use commands not supported by Servo (like the 'spin' instruction) this is how you can do it. Double click on the code grip to add a code fragment. You'll get a text box to type in your code. The code snippet can be dragged around on its grip to occur at the proper time. Double clicking on an existing snippet will let you edit it again.

Layout handles
Drag these to resize the tree view and timeline bay.

The Timeline View Controls:
As stated previously, the x-axis of the timeline represents time. When your animation gets longer than the timeline, or highly detailed, you'll probably want to be able to zoom in and out, right? That's what the Timeline View Controls are for.

The view controls consist of a beefy horizontal scrollbar nestled between two NEFs.
The left NEF represents the length of the timeline in time incriments. Changes to this NEF will cause the view to zoom in or out. Note that the ruler-markings on the main grip scale up seamlessly to prevent overcrowding, because I kick ass :)
The right NEF represents the end-time of the animation. If this value is less than the left NEF (timeline view length) then scrolling is impossible (and unnecessary) because the view can contain the entire animation. However, if the length of the animation is greater than the length of the view (i.e. you are zoomed in), you will be able to scroll around using the scrollbar in the middle.

Playback Controls:
If these aren't self-explanitory, then I give up :)

That pretty much sums it up...
It may seem complicated at first, but in action, Servo is very easy to use. A brief tutorial will demonstrate...

Tutorial:
This tutorial assumes you have access to the arm peewee 3do (armpw.3do).
1) Load up the peewee 3do. (object->load)
2) Bring the left arm to the foreground and make it active. (Tree View->click on left arm twice)
3) Create an index at around time 300. (Timeline Bay->click at around 300)
Notice that the Current Time carat has jumped to the index you just created.
4) Move the mouse left and right over the index.
Notice that when the mouse goes to the left of the new index, the Current Time carat jumps to time 0, and when you move to the right of the new index, the carat jumps back to it.
5) Exit the Timeline Bay with the carat on the new index.
You are now editing the left arm's instructions at time ~300.
6) Left-drag on the left arm in the 3d view. Rotate it some.
Note that a yellow mark has appeared where the index crosses the left arm's grip in the Timeline Bay. This represents the instructions you have just created.
Also note, the old position of the arm shows up as a ghosted trail.
7) Repeat step 4.
Notice that the arm now jumps between the old and new rotation values when you cross the index.
Also notice that when viewing frame zero, the 'next ahead' position at frame 300 is projected as an outline.
8) Create a new index at frame ~150.
9) Using the ghosted trail and future outline as guides, position the arm roughly halfway between the 'last' and 'next' values.
10) Repeat this a few times, observing that the percieved motion when you scrub the view becomes smoother.
11) Now, try grabbing one of the index flags and move the index around.
12) Try dragging the mouse on the main grip; notice that all indexes after the Current Time move.

13) Create a killer animation.

-Rhad


Revisions for release Nov_26_2000:


Fixed miscalculation of final frame duration on load/save.
Avoided malfunction that occurs when one frame is dragged past another; in present version, frames cannot be dragged past one another. They have a 1-tic buffer.
Fixed bug of indestructable code blocks: now, if you edit a code block and delete all of the text, the code block will evaporate.
Fixed 'BOS:save' menu item.
Fixed 'BOS:new' menu item.
Fixed behavior of the timeline scroll bar. The scroll bar now behaves appropriately when you change the offset and range of the timeline view. Also, the scroll bar now has full functionality (including one-tic scrolling with the arrows, and page-by-page scrolling if you click in the track).
Fixed the finicky nature of foreground indexes. In the initial release, Servo purged the foreground of unused indexes whenever the foreground changed; this included any time a new piece was brought to the foreground and any time the active piece changed... So, if you set an index and then selected a new active piece to animate, the new index evaporated before you could use it. Quite annoying.
In the present version, the foreground is purged of unused indexes ONLY if a foreground piece moves to the background; thus the environment is much more stable and friendly.


Added functionality: the text of a code block is drawn underneath it on the timeline for easier identification.
Added functionality: pressing the 'delete' key while in the timeline will delete the current index and ALL foreground instructions at the current time.


Known Bugs in release Sept_12_2000:

High Priority bugs
BUG:
Servo miscalculates (MASSIVELY miscalculates) the duration of the final frame.
By design, servo is supposed to end the animation with one final 'sleep' statement which covers the difference between the final frame time and the end of animation time. Currently, servo buggers up the process and adds a huge sleep.
Workaround:
Edit the text output manually to remove/repair the eronious sleep statement.
BUG:
If you drag a keyframe past another keyframe (thereby changing their order in time) servo gets confused and screws up the instruction lists for individual pieces.
Workaround:
Currently there is no workaround for this problem. For the moment, you'll just have to avoid the problem by not dragging one key past another. Sorry.

Medium Priority bugs
BUG:
There is no way to remove a code key.
Code keys are supposed to automatically self-eliminate if you remove all the text - but obviously this function is broken right now.
Workaround:
If you need to remove a code key, empty all the text in it, then save and re-open the anim.
BUG:
The mouse mode 'move' is disabled. Workaround: Use the instruction editor for move commands.

Low Priority bugs
BUG:
Minimizing servo will cause the horizontal layout bar to go to the lowest position, causing the keyframe bay to 'dissappear'.
Workaround:
Just pull it back up.
BUG:
The 'save' button is currently dead.
Workaround:
Use 'save as'.

Stop software piracy - make everything freeware!